﻿using AIStudio.Core;
using AIStudio.Wpf.BasePage.Events;
using AIStudio.Wpf.BasePage.Models;
using AIStudio.Wpf.Business;
using AIStudio.Wpf.DemoPage.Service;
using AIStudio.Wpf.HomePage.Views;
using AIStudio.Wpf.PetaPoco;
using AIStudio.Wpf.Service.AppClient;
using AIStudio.Wpf.Service.IAppClient;
using AIStudio.Wpf.Service.IWebSocketClient;
using AIStudio.Wpf.Service.WebSocketClient;
using AutoMapper;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Util.Controls;
using Util.Controls.Data;
using Util.Controls.DialogBox;

namespace AIStudio.Wpf.HomePage.ViewModels
{
    class MainViewModel : Prism.Mvvm.BindableBase
    {
        protected IContainerExtension _container { get; }
        protected IRegionManager _regionManager { get; }
        protected IEventAggregator _aggregator { get; }
        protected IOperator _operator { get; }
        protected IDataProvider _dataProvider { get; }
        protected IWSocketClient _wSocketClient { get; }
        protected ILocalSetting _localSetting { get; }
        protected IMapper _mapper { get; }


        public MainViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator aggregator, IOperator ioperator, IDataProvider dataProvider, IWSocketClient wSocketClient, ILocalSetting localSetting, IMapper mapper)
        {
            _container = container;
            _regionManager = regionManager;
            _aggregator = aggregator;
            _operator = ioperator;
            _dataProvider = dataProvider;
            _wSocketClient = wSocketClient;
            _localSetting = localSetting;
            _mapper = mapper;

            InitData();

            Screenshot.Snapped -= Screenshot_Snapped;
            Screenshot.Snapped += Screenshot_Snapped;
            _aggregator.GetEvent<LoginSentEvent>().Subscribe(LoginSentEventReceived);
            _aggregator.GetEvent<KeyExcuteEvent>().Subscribe(KeyExcuteEventReceived);
            _aggregator.GetEvent<MenuClickEvent>().Subscribe(MenuClickEventReceived, ThreadOption.PublisherThread, false, item => string.IsNullOrEmpty(item.Label));

            var section = LocalSetting.GetSection("usersetting") as UserSettingSection;
            if (section != null && section.ToolItems != null)
            {
                ToolItems = new ObservableCollection<AToolItem>(section.ToolItems.OfType<ToolItem>().ChangeType<List<AToolItem>>());
            }
        }

        private void LoginSentEventReceived(bool loginState)
        {
            if (loginState == true)
            {
                InitData();
            }
        }

        private void KeyExcuteEventReceived(string key)
        {
            KeyExcute(key);
        }

        private async void InitData()
        {
            LocalSetting = _localSetting as LocalSetting;
            Operator = _operator as Operator;
            WSocketClient = _wSocketClient as WSocketClient;

            if (_operator.UserName != "LocalUser")
            {
                try
                {
                    var control = WindowBase.ShowWaiting(WaitingType.Progress, "RootWindow");
                    control.WaitInfo = "正在获取用户信息";
                    var userinfo = await _dataProvider.GetData<UserInfoPermissions>("/Base_Manage/Home/GetOperatorInfo");
                    if (!userinfo.IsOK)
                    {
                        throw new System.Exception(userinfo.ErrorMessage);
                    }

                    _operator.Property = userinfo.ResponseItem.UserInfo;
                    _operator.Permissions = userinfo.ResponseItem.Permissions;
                    _operator.Avatar = userinfo.ResponseItem.UserInfo.Avatar;

                    control.WaitInfo = "正在获取菜单信息";
                    var menuinfo = await _dataProvider.GetData<List<Base_ActionTree>>("/Base_Manage/Home/GetMenuList");
                    if (!menuinfo.IsOK)
                    {
                        throw new System.Exception(menuinfo.ErrorMessage);
                    }
                    BuildMenu(menuinfo.ResponseItem);

                    //连接socket
                    _wSocketClient.InitAndStart(_localSetting.ServerIP, $"{_localSetting.ServerIP.Replace("http", "ws")}/ws?userName={_operator.Property.UserName}&userId={_operator.Property.Id}");
                    _wSocketClient.MessageReceived -= _wSocketClient_MessageReceived;
                    _wSocketClient.MessageReceived += _wSocketClient_MessageReceived;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    WindowBase.HideWaiting("RootWindow");
                }
            }

#if DEBUG
            AMenuItem code = new AMenuItem() { Glyph = "code", Label = "开发", Code = "Demo", Type = 0 };
            MenuItems.Add(code);

            AMenuItem subcode = null;
            if (_operator.UserName != "LocalUser")
            {
                subcode = new AMenuItem() { Glyph = "code", Label = "辅助工具", Code = "Demo", Type = 0 };
                subcode.AddChildren(new AMenuItem() { Label = "数据库连接", Code = "Base_DbLinkViewModel", Type = 1 });
                subcode.AddChildren(new AMenuItem() { Label = "代码生成", Code = "BuildCodeViewModel", Type = 1 });
                subcode.AddChildren(new AMenuItem() { Label = "Swagger", Code = "SwaggerViewModel", Type = 1 });
                code.AddChildren(subcode);
            }

            var demoinfo = DataService.GetDemoInfo();
            foreach (var info in demoinfo)
            {
                subcode = new AMenuItem() { Glyph = "code", Label = info.Title, Code = "Demo", Type = 0 };
                code.AddChildren(subcode);

                foreach (var item in info.DemoItemList)
                {
                    var aMenuItem = new AMenuItem() { Label = item.Name, Code = $"{item.TargetCtlName}Model", Type = 1 };
                    subcode.AddChildren(aMenuItem);
                }
            }

#endif
            var tool = new AMenuItem() { Glyph = "tool", Label = "工具", Code = "Tool", Type = 0 };
            var screenshot = new AMenuItem() { Label = "截屏", Code = "Screenshot", Type = 1 };
            tool.AddChildren(screenshot);
            MenuItems.Add(tool);

            var winStatus = new AMenuItem() { Glyph = "windows", Label = (string)Application.Current.Resources["窗口"], Code = "WinStatus", Type = 0 };
            var showTitleBar = new AMenuItem() { Label = (string)Application.Current.Resources["标题显示"], Code = "ShowTitleBar", Type = 1, IsChecked = WindowBase.GetWindowStatus("ShowTitleBar", "RootWindow") };
            var showInTaskbar = new AMenuItem() { Label = (string)Application.Current.Resources["任务栏显示"], Code = "ShowInTaskbar", Type = 1, IsChecked = WindowBase.GetWindowStatus("ShowInTaskbar", "RootWindow") };
            var topmost = new AMenuItem() { Label = (string)Application.Current.Resources["总在最前"], Code = "Topmost", Type = 1, IsChecked = WindowBase.GetWindowStatus("Topmost", "RootWindow") };
            var toggleFullScreen = new AMenuItem() { Label = (string)Application.Current.Resources["最大化全屏"], Code = "ToggleFullScreen", Type = 1, IsChecked = WindowBase.GetWindowStatus("ToggleFullScreen", "RootWindow") };
            var notifyIcon = new AMenuItem() { Label = (string)Application.Current.Resources["托盘显示"], Code = "ShowNotifyIcon", Type = 1 };
            winStatus.AddChildren(showTitleBar);
            winStatus.AddChildren(showInTaskbar);
            winStatus.AddChildren(topmost);
            winStatus.AddChildren(toggleFullScreen);
            winStatus.AddChildren(notifyIcon);
            MenuItems.Add(winStatus);

            _totalMenus = AddTotalMenu(MenuItems);
        }

        private void _wSocketClient_MessageReceived(WSMessageType type, string message)
        {
            if (type == WSMessageType.PushType)
            {

            }
        }

        private void BuildMenu(List<Base_ActionTree> base_Actions)
        {
            var nodes = base_Actions.Where(p => string.IsNullOrEmpty(p.ParentId));
            foreach (var node in nodes)
            {
                AMenuItem aMenuItem = new AMenuItem() { Glyph = node.Icon, Label = node.Name, Code = node.Url, Type = node.Type, ParentId = node.ParentId, Id = node.Id };
                MenuItems.Add(aMenuItem);
                SubBuildMenu(aMenuItem, base_Actions, aMenuItem.Id);
            }
        }

        private void SubBuildMenu(AMenuItem menuItem, List<Base_ActionTree> base_Actions, string parentid)
        {
            var nodes = base_Actions.Where(p => p.ParentId == parentid);
            foreach (var node in nodes)
            {
                AMenuItem aMenuItem = new AMenuItem() { Glyph = node.Icon, Label = node.Name, Code = node.Url, Type = node.Type, ParentId = node.ParentId, Id = node.Id };
                menuItem.AddChildren(aMenuItem);
                SubBuildMenu(aMenuItem, base_Actions, aMenuItem.Id);
            }
        }

        private List<AMenuItem> AddTotalMenu(IEnumerable<AMenuItem> items)
        {
            List<AMenuItem> list = new List<AMenuItem>();
            foreach (var item in items)
            {
                if (item.Type == 1)
                {
                    list.Add(item);
                }
                if (item.Children != null)
                {
                    list.AddRange(AddTotalMenu(item.Children.OfType<AMenuItem>()));
                }
            }
            return list;
        }



        private void Screenshot_Snapped(object sender, FunctionEventArgs<ImageSource> e)
        {
            Clipboard.SetImage((System.Windows.Media.Imaging.BitmapSource)e.Info);

            if (Screenshot.ShowDialog)
            {
                Util.Controls.Windows.ImageBrowser imageBrowser = new Util.Controls.Windows.ImageBrowser((System.Windows.Media.Imaging.BitmapSource)e.Info);
                imageBrowser.Show();

                //new Util.Controls.Windows.Window
                //{
                //    Content = new Image
                //    {
                //        Source = e.Info,
                //        Stretch = Stretch.None
                //    },
                //    WindowStartupLocation = WindowStartupLocation.CenterScreen

                //}.ShowDialog();
            }
        }

        private LocalSetting @localSetting;
        public LocalSetting LocalSetting
        {
            get { return @localSetting; }
            set
            {
                if (@localSetting != value)
                {
                    SetProperty(ref @localSetting, value);
                }
            }
        }


        private Operator @operator;
        public Operator Operator
        {
            get { return @operator; }
            set
            {
                if (@operator != value)
                {
                    SetProperty(ref @operator, value);
                }
            }
        }

        private WSocketClient @wSocketClient;
        public WSocketClient WSocketClient
        {
            get { return @wSocketClient; }
            set
            {
                if (@wSocketClient != value)
                {
                    SetProperty(ref @wSocketClient, value);
                }
            }
        }

        private string _searchText;
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                if (_searchText != value)
                {
                    SetProperty(ref _searchText, value);
                    Search(value);
                }
            }
        }

        private List<AMenuItem> _totalMenus = new List<AMenuItem>();

        private ObservableCollection<AMenuItem> _searchMenus = new ObservableCollection<AMenuItem>();
        public ObservableCollection<AMenuItem> SearchMenus
        {
            get { return _searchMenus; }
            set
            {
                if (_searchMenus != value)
                {
                    SetProperty(ref _searchMenus, value);
                }
            }
        }


        private ObservableCollection<AMenuItem> _menuItems = new ObservableCollection<AMenuItem>();
        public ObservableCollection<AMenuItem> MenuItems
        {
            get { return _menuItems; }
            set
            {
                if (_menuItems != value)
                {
                    SetProperty(ref _menuItems, value);
                }
            }
        }

        private AMenuItem _selectedMenuItem;
        public AMenuItem SelectedMenuItem
        {
            get { return _selectedMenuItem; }
            set
            {
                SetProperty(ref _selectedMenuItem, value);
                SelectedMenuItemChanged(value);
            }
        }

        private ObservableCollection<AToolItem> _toolItems = new ObservableCollection<AToolItem>();
        public ObservableCollection<AToolItem> ToolItems
        {
            get { return _toolItems; }
            set
            {
                if (_toolItems != value)
                {
                    SetProperty(ref _toolItems, value);
                }
            }
        }

        private ICommand _systemManageCommand;
        public ICommand SystemManageCommand
        {
            get
            {
                return this._systemManageCommand ?? (this._systemManageCommand = new DelegateCommand<string>(para => this.SystemManage(para)));
            }
        }

        private ICommand _userDropCommand;
        public ICommand UserDropCommand
        {
            get
            {
                return this._userDropCommand ?? (this._userDropCommand = new DelegateCommand<string>(para => this.UserDrop(para)));
            }
        }

        private ICommand _titleClickCommand;
        public ICommand TitleClickCommand
        {
            get
            {
                return this._titleClickCommand ?? (this._titleClickCommand = new DelegateCommand<object>(para => this.TitleClick(para)));
            }
        }

        private ICommand _searchCommand;
        public ICommand SearchCommand
        {
            get
            {
                return this._searchCommand ?? (this._searchCommand = new DelegateCommand<AMenuItem>(para => this.Search(para)));
            }
        }

        private ICommand _toolBarConfigCommand;
        public ICommand ToolBarConfigCommand
        {
            get
            {
                return this._toolBarConfigCommand ?? (this._toolBarConfigCommand = new DelegateCommand(() => this.ToolBarConfig()));
            }
        }

        private void SystemManage(string para)
        {
            switch (para)
            {
                case "Setting":
                    {
                        var flyout = new SystemSetView();
                        // when the flyout is closed, remove it from the hosting FlyoutsControl
                        WindowBase.ShowFlyout(flyout, "RootWindow");
                        break;
                    }
                case "Logs":
                    {
                        string dir = System.AppDomain.CurrentDomain.BaseDirectory + "Logs";
                        System.Diagnostics.Process.Start("explorer.exe", Path.GetFullPath(dir));
                        break;
                    }
            }
        }

        private async void UserDrop(string para)
        {
            switch (para)
            {
                case "Logout":
                    {
                        var sure = await Msg.Question("确认退出吗?", BoxType.Metro);
                        if (sure == BaseDialogResult.OK)
                        {
                            //注销操作成功后，发送消息
                            _aggregator.GetEvent<LoginSentEvent>().Publish(false);
                        }
                        break;
                    }
            }
        }

        private void KeyExcute(string key)
        {
            switch (key)
            {
                case "F10":
                    {
                        new Screenshot().Start();
                        break;
                    }
                case "F11":
                    {
                        WindowBase.SetWindowStatus("ToggleFullScreen", "RootWindow");
                        break;
                    }
            }
        }

        private void TitleClick(object para)
        {
            WindowBase.SetWindowStatus("WindowState", "RootWindow");
        }

        private void MenuClickEventReceived(AMenuItem obj)
        {
            SelectedMenuItem = obj;
        }

        void SelectedMenuItemChanged(AMenuItem item)
        {
            if (item == null || string.IsNullOrEmpty(item.Code))
            {
                return;
            }


            string parentcode = string.Empty;
            if (item.Parent != null)
            {
                parentcode = item.Parent.Code;
            }
            else if (item is AToolItem)
            {
                parentcode = (item as AToolItem).ParentCode;
                if (!_totalMenus.Any(p => p.Code == item.Code))
                {
                    MessageBoxHelper.ShowWarning("您没有该菜单的权限");
                    return;
                }
            }

            if (string.IsNullOrEmpty(item.Label))//有的界面程序内部用Code传过来的。
            {
                item.Label = _totalMenus.FirstOrDefault(p => p.Code == item.Code)?.Label;
            }

            if (parentcode == "WinStatus")
            {
                item.IsChecked = WindowBase.SetWindowStatus(item.Code, "RootWindow");
                return;
            }
            else if (parentcode == "Tool")
            {
                if (item.Code == "Screenshot")
                {
                    new Screenshot().Start();
                }
                return;
            }


            _aggregator.GetEvent<MenuClickEvent>().Publish(item);
        }

        void Search(AMenuItem item)
        {
            if (item == null)
            {
                item = SearchMenus.FirstOrDefault();
            }
            SelectedMenuItemChanged(item);
            SearchText = null;
        }

        void Search(string text)
        {
            if (!string.IsNullOrEmpty(text))
            {
                SearchMenus = new ObservableCollection<AMenuItem>(_totalMenus.Where(p => p.Label.ToLower().Contains(text.ToLower()) || (!string.IsNullOrEmpty(p.Code) && p.Code.ToLower().Contains(text.ToLower()))));
            }
            else
            {
                SearchMenus = new ObservableCollection<AMenuItem>();
            }
        }

        async void ToolBarConfig()
        {
            var viewmodel = new ToolBarSetViewModel(MenuItems, _mapper.Map<List<AToolItem>>(ToolItems));

            var dialog = new ToolBarSetView(viewmodel);
            var res = (BaseDialogResult)await WindowBase.ShowDialogAsync(dialog, "RootWindow");
            if (res == BaseDialogResult.OK)
            {
                var section = new UserSettingSection();
                ToolItems toolItems = new ToolItems();
                toolItems.AddRange(viewmodel.ToolItems.ChangeType<List<ToolItem>>());
                section.ToolItems = toolItems;
                LocalSetting.SetSection("usersetting", section);

                ToolItems = viewmodel.ToolItems;

            }
        }
    }
}
